import {ISoundAgent} from "./ISoundAgent";
import {ISoundAgentHelper} from "./ISoundAgentHelper";
import { SoundGroup } from "./SoundGroup";
import {ISoundHelper} from "./ISoundHelper";
import {ResetSoundAgentEventArgs} from "./ResetSoundAgentEventArgs";
import {ISoundGroup} from "./ISoundGroup";
import {Sound_Constant} from "./Constant";

export class SoundAgent implements ISoundAgent{
    get setSoundAssetTime(): Date {
        return this._setSoundAssetTime;
    }
    get Helper(): ISoundAgentHelper {
        return this._soundAgentHelper;
    }
    get DopplerLevel(): number {
        return this._soundAgentHelper.DopplerLevel;
    }

    set DopplerLevel(value: number) {
        this._soundAgentHelper.DopplerLevel = value;
    }
    get MaxDistance(): number {
        return this._soundAgentHelper.MaxDistance;
    }

    set MaxDistance(value: number) {
        this._soundAgentHelper.MaxDistance = value;
    }
    get SpatialBlend(): number {
        return this._soundAgentHelper.SpatialBlend;
    }

    set SpatialBlend(value: number) {
        this._soundAgentHelper.SpatialBlend = value;
    }
    get PanStereo(): number {
        return this._soundAgentHelper.PanStereo;
    }

    set PanStereo(value: number) {
        this._soundAgentHelper.PanStereo = value;
    }
    get Pitch(): number {
        return this._soundAgentHelper.Pitch;
    }

    set Pitch(value: number) {
        this._soundAgentHelper.Pitch = value;
    }
    get VolumeInSoundGroup(): number {
        return this._volumeInSoundGroup;
    }

    set VolumeInSoundGroup(value: number) {
        this._volumeInSoundGroup = value;
        this.RefreshVolume();
    }
    get Volume(): number {
        return this._soundAgentHelper.Volume;
    }


    get Priority(): number {
        return this._soundAgentHelper.Priority;
    }

    set Priority(value: number) {
        this._soundAgentHelper.Priority = value;
    }
    get Loop(): boolean {
        return this._soundAgentHelper.Loop;
    }

    set Loop(value: boolean) {
        this._soundAgentHelper.Loop = value;
    }
    get MuteInSoundGroup(): boolean {
        return this._muteInSoundGroup;
    }

    set MuteInSoundGroup(value:boolean){
        this._muteInSoundGroup = value;
        this.RefreshMute();
    }
    get Mute(): boolean {
        return this._soundAgentHelper.Mute;
    }
    get Time(): number {
        return this._soundAgentHelper.Time;
    }

    set Time(value: number) {
        this._soundAgentHelper.Time = value;
    }
    get Length(): number {
        return this._soundAgentHelper.Length;
    }
    get IsPlaying(): boolean {
        return this._soundAgentHelper.IsPlaying;
    }
    get SerialId(): number {
        return this._serialId;
    }

    set SerialId(value: number) {
        this._serialId = value;
    }
    get SoundGroup(): ISoundGroup {
        return this._SoundGroup;
    }
    private _SoundGroup: SoundGroup;

    private readonly _soundGroup:SoundGroup;
    private readonly _soundHelper:ISoundHelper;
    private readonly _soundAgentHelper:ISoundAgentHelper;

    private _serialId:number;
    private _soundAsset;
    private _setSoundAssetTime:Date;
    private _muteInSoundGroup:boolean;
    private _volumeInSoundGroup:number;





    constructor(soundGroup:SoundGroup,soundHelper:ISoundHelper,soundAgentHelper:ISoundAgentHelper) {
        if (soundGroup == null)
        {
            throw new Error("Sound group is invalid.");
        }

        if (soundHelper == null)
        {
            throw new Error("Sound helper is invalid.");
        }

        if (soundAgentHelper == null)
        {
            throw new Error("Sound agent helper is invalid.");
        }

        this._soundGroup = soundGroup;
        this._soundHelper = soundHelper;
        this._soundAgentHelper = soundAgentHelper;
        this._soundAgentHelper.ResetSoundAgent = this.OnResetSoundAgent;
        this._serialId = 0;
        this._soundAsset = null;
        this.Reset();

    }




    Pause(fadeOutSeconds?: number): void {
        if(fadeOutSeconds){
            this._soundAgentHelper.Pause(fadeOutSeconds);
        }else{
            this._soundAgentHelper.Pause(Sound_Constant.DefaultFadeOutSeconds);
        }
    }

    Play(fadeInSeconds?: number): void {
        if(fadeInSeconds){
            this._soundAgentHelper.Play(fadeInSeconds);
        }else{
            this._soundAgentHelper.Play(Sound_Constant.DefaultFadeInSeconds);
        }
    }

    Reset(): void {
        if (this._soundAsset != null)
        {
            //this._soundHelper.ReleaseSoundAsset(this._soundAsset);
            this._soundAsset = null;
        }

        this._setSoundAssetTime = new Date(1970,1,1,0,0,0);
        this.Time = Sound_Constant.DefaultTime;
        this.MuteInSoundGroup = Sound_Constant.DefaultMute;
        this.Loop = Sound_Constant.DefaultLoop;
        this.Priority = Sound_Constant.DefaultPriority;
        this.VolumeInSoundGroup = Sound_Constant.DefaultVolume;
        this.Pitch = Sound_Constant.DefaultPitch;
        this.PanStereo = Sound_Constant.DefaultPanStereo;
        this.SpatialBlend = Sound_Constant.DefaultSpatialBlend;
        this.MaxDistance = Sound_Constant.DefaultMaxDistance;
        this.DopplerLevel = Sound_Constant.DefaultDopplerLevel;
        this._soundAgentHelper.Reset();
    }

    Resume(fadeInSeconds?: number): void {
        if(fadeInSeconds){
            this._soundAgentHelper.Resume(fadeInSeconds);
        }else{
            this._soundAgentHelper.Resume(Sound_Constant.DefaultFadeInSeconds);
        }
    }

    Stop(fadeOutSeconds?: number): void {
        if(fadeOutSeconds){
            this._soundAgentHelper.Stop(fadeOutSeconds);
        }else{
            this._soundAgentHelper.Stop(Sound_Constant.DefaultFadeOutSeconds);
        }
    }

    private OnResetSoundAgent(sender,e:ResetSoundAgentEventArgs) {
        this.Reset();
    }

    public RefreshMute():void {
        this._soundAgentHelper.Mute = this._soundGroup.Mute || this._muteInSoundGroup;
    }

    public RefreshVolume():void {
        this._soundAgentHelper.Volume = this._soundGroup.Volume * this._volumeInSoundGroup;
    }

    public SetSoundAsset(soundAsset):boolean{
        this.Reset();
        this._soundAsset = soundAsset;
        this._setSoundAssetTime = new Date();
        return this._soundAgentHelper.SetSoundAsset(soundAsset);
    }

}